package com.qdaily.ui.ui.views.radar;

import android.content.Context;
import android.graphics.*;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.qdaily.supportlibrary.util.LocalDisplay;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class SpiderWebChart extends View {

    /**
     * 默认数据的显示颜色
     */
    public static final int[] COLORS = {0xFFFFC81F, 0x0DFFC81F};

    /**
     * 图表数据
     */
    protected List<TitleValueEntity> data = new ArrayList<>();

    /**
     * 经线数量
     */
    protected int longitudeNum = 5;

    private int longitudeLength = 80;
    private int longitudeInsideLength = longitudeLength - 10;

    private Point position = new Point(0, 0);
    private Paint mPaintWebFill;
    private Paint mPaintWebInsideFill;
    private Paint mPaintWebBorder;
    private Paint mPaintFont;
    private Paint mPaintPoint;
    private Paint mPaintInsidePoint;

    public SpiderWebChart(Context context) {
        this(context, null);
    }

    public SpiderWebChart(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SpiderWebChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        for (int i = 0; i < longitudeNum; i++) {
            data.add(new TitleValueEntity("", 0.5f * 10f, 0));
        }
        // 背景色。
        mPaintWebFill = new Paint();
        mPaintWebFill.setColor(radarOutsideBgColor);
        mPaintWebFill.setAntiAlias(true);
        // 背景色里面的背景
        mPaintWebInsideFill = new Paint();
        mPaintWebInsideFill.setColor(radarInsideBgColor);
        mPaintWebInsideFill.setAntiAlias(true);
        // 外边框
        mPaintWebBorder = new Paint();
        mPaintWebBorder.setColor(Color.BLACK);
        mPaintWebBorder.setStyle(Style.STROKE);
        mPaintWebBorder.setStrokeWidth(2);
        mPaintWebBorder.setAntiAlias(true);
        // 写文字
        mPaintFont = new Paint();
        mPaintFont.setTextSize(LocalDisplay.designedDP2px(10f));
        mPaintFont.setAntiAlias(true);
        mPaintFont.setColor(Color.WHITE);
        // 四周的圆点外
        mPaintPoint = new Paint();
        mPaintPoint.setColor(COLORS[1]);
        mPaintPoint.setAntiAlias(true);
        //四周的圆点内
        mPaintInsidePoint = new Paint();
        mPaintInsidePoint.setColor(COLORS[0]);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // get safe rect
        int rect = super.getHeight();

        // calculate longitude length
        longitudeLength = (int) ((rect / 2f) * 0.8);
        longitudeInsideLength = (int) ((rect / 2f) * 0.7);

        // calculate position
        position = new Point((int) (super.getWidth() / 2f), (int) (super.getHeight() / 2f));

        // draw this chart
        drawWeb(canvas);

        // draw data on chart
        drawData(canvas);
    }

    /**
     * 根据纬度参数的数据计算需要在图上绘制的纬线的点
     *
     * @param pos 纬度
     * @return　List<PointF> 计算结果
     */
    protected List<PointF> getWebAxisPoints(float pos) {
        List<PointF> points = new ArrayList<PointF>();
        for (int i = 0; i < longitudeNum; i++) {
            PointF pt = new PointF();
            float offsetX = (float) (position.x - longitudeLength * pos * Math.sin(i * 2 * Math.PI / longitudeNum));
            float offsetY = (float) (position.y - longitudeLength * pos * Math.cos(i * 2 * Math.PI / longitudeNum));
            pt.set(offsetX, offsetY);

            points.add(pt);
        }
        return points;
    }

    //设计的是，里面嵌套一层web
    protected List<PointF> getWebAxisInsidePoints(float pos) {
        List<PointF> points = new ArrayList<PointF>();
        for (int i = 0; i < longitudeNum; i++) {
            PointF pt = new PointF();
            float offsetX = (float) (position.x - longitudeInsideLength * pos * Math.sin(i * 2 * Math.PI / longitudeNum));
            float offsetY = (float) (position.y - longitudeInsideLength * pos * Math.cos(i * 2 * Math.PI / longitudeNum));
            pt.set(offsetX, offsetY);

            points.add(pt);
        }
        return points;
    }

    /**
     * 根据参数的数据计算需要在图上绘制的点
     *
     * @param data 计算用的数据
     * @return　List<PointF> 计算结果
     */
    protected List<PointF> getDataPoints(List<TitleValueEntity> data) {
        List<PointF> points = new ArrayList<PointF>();
        for (int i = 0; i < longitudeNum; i++) {
            PointF pt = new PointF();
            float offsetX = (float) (position.x - data.get(i).getValue() / 10f * longitudeLength * Math.sin(i * 2 * Math.PI / longitudeNum));
            float offsetY = (float) (position.y - data.get(i).getValue() / 10f * longitudeLength * Math.cos(i * 2 * Math.PI / longitudeNum));
            pt.set(offsetX, offsetY);

            points.add(pt);
        }
        return points;
    }

    /**
     * 绘制蜘蛛网
     *
     * @param canvas Canvas
     */

    private int radarOutsideBgColor = 0x33000000;
    private int radarInsideBgColor = 0x33000000;
    private HashMap<Integer, Rect> titleOnClick = new HashMap<>();

    protected void drawWeb(Canvas canvas) {
        //线
        Path mPath = new Path();
        List<PointF> pointList = getWebAxisPoints(1);
        Path mInsidePath = new Path();
        List<PointF> pointInsideList = getWebAxisInsidePoints(1);

        // draw border
        if (null != data) {
            for (int i = 0; i < pointList.size(); i++) {
                PointF pt = pointList.get(i);
                PointF ptInside = pointInsideList.get(i);
                if (i == 0) {
                    mPath.moveTo(pt.x, pt.y);
                    mInsidePath.moveTo(ptInside.x, ptInside.y);
                } else {
                    mPath.lineTo(pt.x, pt.y);
                    mInsidePath.lineTo(ptInside.x, ptInside.y);
                }

                // draw title
                String title = data.get(i).getTitle();
                float realx = 0;
                float realy = 0;

                if (pt.x < position.x) {
                    realx = pt.x - mPaintFont.measureText(title);
                } else if (pt.x > position.x) {
                    realx = pt.x + 10;
                } else {
                    realx = pt.x - mPaintFont.measureText(title) / 2;
                }

                if (pt.x < position.x && pt.y > position.y) {
                    realx = pt.x - mPaintFont.measureText(title) - 20;
                }

                if (pt.x < position.x && pt.y < position.y) {
                    realx = pt.x - mPaintFont.measureText(title) + 10;
                }

                if (pt.y > position.y) {
                    realy = pt.y + 25;
                } else if (pt.y < position.y) {
                    realy = pt.y - 25;
                } else {
                    realy = pt.y - 25;
                }

                canvas.drawText(title, realx, realy, mPaintFont);

                Rect rect = new Rect();
                rect.set((int) realx - (int) mPaintFont.measureText(title) / 2,
                        (int) realy - (int) mPaintFont.measureText(title) / 2,
                        (int) realx + (int) mPaintFont.measureText(title),
                        (int) realy + (int) mPaintFont.measureText(title));
                titleOnClick.put(i, rect);
            }
        }

        mPath.close();
        mInsidePath.close();

        canvas.drawPath(mPath, mPaintWebFill);
        canvas.drawPath(mInsidePath, mPaintWebInsideFill);

        // 画外边框的圆点
        for (int i = 0; i < pointList.size(); i++) {
            PointF pt = pointList.get(i);
            canvas.drawCircle(pt.x - 3, pt.y - 3, 15, mPaintPoint);
            canvas.drawCircle(pt.x - 3, pt.y - 3, 6, mPaintInsidePoint);
        }
    }

    private int onTouchX = 0;
    private int onTouchY = 0;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                onTouchX = (int) event.getX();
                onTouchY = (int) event.getY();
                break;
            case MotionEvent.ACTION_UP:
                for (int i = 0; i < titleOnClick.size(); i++) {
                    Rect rect = titleOnClick.get(i);
                    if (rect.contains(onTouchX, onTouchY)) {
                        if (null != iSpiderWeChartOnClikc) {
                            iSpiderWeChartOnClikc.onClick(data.get(i));
                        }
                    }
                }
                break;
        }
        return true;
    }

    private ISpiderWeChartOnClikc iSpiderWeChartOnClikc;

    public void setiSpiderWeChartOnClikc(ISpiderWeChartOnClikc iSpiderWeChartOnClikc) {
        this.iSpiderWeChartOnClikc = iSpiderWeChartOnClikc;
    }

    public interface ISpiderWeChartOnClikc {
        void onClick(TitleValueEntity titleValueEntity);
    }

    /**
     * 将数据绘制在图表上
     *
     * @param canvas
     */
    protected void drawData(Canvas canvas) {
        if (null != data) {
            // 画里边的虚影
            Paint mPaintFill = new Paint();
            mPaintFill.setColor(COLORS[0]);
            mPaintFill.setStyle(Style.FILL);
            mPaintFill.setAntiAlias(true);
            mPaintFill.setAlpha(20);

            // 画里边的外边框
            Paint mPaintBorder = new Paint();
            mPaintBorder.setColor(COLORS[0]);
            mPaintBorder.setStyle(Style.STROKE);
            mPaintBorder.setStrokeWidth(2);
            mPaintBorder.setAntiAlias(true);

            Path mPath = new Path();

            // get points to draw
            List<PointF> pointList = getDataPoints(data);
            // initialize path
            for (int i = 0; i < pointList.size(); i++) {
                PointF pt = pointList.get(i);
                if (i == 0) {
                    mPath.moveTo(pt.x, pt.y);
                } else {
                    mPath.lineTo(pt.x, pt.y);
                }
                // canvas.drawCircle(pt.x, pt.y, 3, mPaintPoint);
            }
            mPath.close();

            canvas.drawPath(mPath, mPaintFill);
            canvas.drawPath(mPath, mPaintBorder);
        }
    }

    /**
     * @return the data
     */
    public List<TitleValueEntity> getData() {
        return data;
    }

    /**
     * @param data the data to set
     */
    public void setData(List<TitleValueEntity> data) {
        this.data = data;
        this.invalidate();
        this.postInvalidate();
    }

    /**
     * @return the longitudeNum
     */
    public int getLongitudeNum() {
        return longitudeNum;
    }

    /**
     * @param longitudeNum the longitudeNum to set
     */
    public void setLongitudeNum(int longitudeNum) {
        this.longitudeNum = longitudeNum;
    }

}
